#include "common.h"
#include "Graphics.h"
#include "Util.h"


using namespace Scenic::Renderer;


extern FormatInfo formats[];
extern IDirect3DDevice9 *direct3DDevice;
extern Capabilities deviceCaps;

static int usedTextureMemory = 0;


VolumeTexture::VolumeTexture(int width, int height, int depth, Format format)
{
	this->texture = 0;
	this->width = width;
	this->height = height;
	this->depth = depth;
	this->format = format;
	levels = 1;

	createTexture();
}

VolumeTexture::~VolumeTexture()
{
	free();
}

IDirect3DBaseTexture9 *VolumeTexture::getTexture()
{
	return texture;
}

void VolumeTexture::createTexture()
{
	if(deviceCaps.textureFormats[format])
		textureFormat = format;
	else
		textureFormat = formats[format].backupFormat;

#if 1
	printf("VolumeTexture::createTexture (width = %d, height = %d, depth = %d, format = %d, textureFormat = %d, levels = %d)\n", 
		width, height, depth, format, textureFormat, levels);
#endif

	HRESULT res;

	res = direct3DDevice->CreateVolumeTexture(width, height, depth, levels, 0, 
		formats[textureFormat].d3dFormat, D3DPOOL_MANAGED, &texture, NULL);

	if(res != D3D_OK) 
	{
		fprintf(stderr, "CreateVolumeTexture failed (result=%s)\n", getErrorName(res));
		fprintf(stderr, "   (width=%d, height=%d, depth=%d, textureFormat=%d)\n", 
			width, height, depth, textureFormat);
		return;
	}
	usedTextureMemory += width * height * depth * formats[textureFormat].size;
}

bool VolumeTexture::contentsLost()
{
	return texture == NULL;
}

void VolumeTexture::free()
{
	if(texture != 0)
	{
		texture->Release();
		texture = 0;
		usedTextureMemory -= width * height * depth * formats[textureFormat].size;
	}
}

void VolumeTexture::write(void *data, Scenic::Renderer::Format format)
{
	D3DLOCKED_BOX lockedBox;
	D3DBOX box;
	HRESULT res;

	if(width == 0 || height == 0 || depth == 0)
	{
		return;
	}

	box.Left = 0;
	box.Right = width;
	box.Top = 0;
	box.Bottom = height;
	box.Front = 0;
	box.Back = depth;

	res = texture->LockBox(0, &lockedBox, NULL, 0);
	if(res != D3D_OK)
	{
		fprintf(stderr, "Locking volume failed: %s\n", getErrorName(res));
		return;
	}

	char *src = (char*)data;
	char *dst = (char*)lockedBox.pBits;
	int pixelSize = Device::getFormatSize(format);

	for(int z = 0; z < depth; z++)
	{
		convert(src + (width * height * pixelSize * z), width * pixelSize, format, 
			dst + (lockedBox.SlicePitch * z), lockedBox.RowPitch, textureFormat,
			width, height);
	} 
	texture->UnlockBox(0);
}
